/*
 * uart_io.c
 *
 * Created: 8/22/2013 3:55:28 PM
 *  Author: Ken Arok
 *
 * \file
 *
 * \brief Input Output Drivers for UART.
 *
 * Copyright (c) 2013 PT Hanindo Automation Solutions. All rights reserved.
 *
 */

#include "config_peripherals.h"

#if UART_PERIPHERAL_ACTIVE

#include "config_ROM_HW.h"
#include "rom.h"
#include "uart.h"
#include "uart_io.h"

void uart_io_init(void)
{
	char com_name[6] = {'C', 'O', 'M', '1', '\0', '\0'};
	com_descriptor_t _uart_desc;
	uint8_t i;

	/* Initialize ROM base address pointer. */
	if(ROM_Base_Block1 == NULL) {
		/* Prepare Copy Block 1 of ROM to RAM. */
		ROM_Base_Block1 = pvPortMalloc(ROM_BLOCK_SIZE);
		if(ROM_Base_Block1 == NULL) {
			while(1);
		}

		if(vReadROM(ROM_BASE_ADDR_BLOK1, ROM_Base_Block1, ROM_BLOCK_SIZE)) {
			while(1);
		}
	}

	/* Initialize UART. */
	uart_init();

	/* Load UART setting from ROM */
	for(i = 1; i < 9; i++) {
		com_name[3] = i + 0x30;
		_uart_desc = uart_io_open((IO_path)com_name, 2);
		if(_uart_desc) {
			uart_io_ctrl(_uart_desc, IORC_LOAD_SETTING_FROM_ROM, NULL);
			uart_io_close(_uart_desc, 2);
		}
	}

	com_name[0] = 'R';
	com_name[1] = 'S';
	com_name[2] = '4';
	com_name[3] = '8';
	com_name[4] = '5';
	com_name[5] = '\0';
	_uart_desc = uart_io_open((IO_path)com_name, 3);
	uart_io_ctrl(_uart_desc, IORC_LOAD_SETTING_FROM_ROM, NULL);
	uart_io_close(_uart_desc, 3);

	com_name[0] = 'T';
	com_name[1] = 'T';
	com_name[2] = 'L';
	com_name[3] = '\0';
	com_name[4] = '\0';
	com_name[5] = '\0';
	_uart_desc = uart_io_open((IO_path)com_name, 3);
	uart_io_ctrl(_uart_desc, IORC_LOAD_SETTING_FROM_ROM, NULL);
	uart_io_close(_uart_desc, 3);
}


portBASE_TYPE uart_io_ctrl(io_descriptor_t io_desc, io_request_code_t reqCode, void *pValue)
{
	portBASE_TYPE _ret_status = pdPASS;
	com_io_options_t *_com_param = pValue;
	uart_options_t *_uart_opt;
	
	switch(reqCode) {
		case IORC_RESTART_MODULE:
			/* Initialize UART. */
			uart_init();
		break;

		case IORC_SET_DEFAULT:
			uart_set_default(io_desc);
		break;

		case IORC_LOAD_SETTING_FROM_ROM:
			uart_load_setting(io_desc);
		break;

		case IORC_SAVE_SETTING_TO_ROM:
			uart_save_setting();
		break;

		case IORC_SET_RX_TIMEOUT:
			uart_rx_timeout(io_desc, *(const uint32_t *)pValue);
		break;

		case IORC_SET_SPEED:
			uart_set_speed(io_desc, *(uint32_t *)pValue);
		break;

		case IORC_SET_DATA_BIT:
			uart_set_databit(io_desc, *(uint8_t *)pValue);
		break;

		case IORC_SET_TRANSFER_POLLED_TX:
			uart_tranfer_mode(io_desc, UART_POLLED_TX);
		break;

		case IORC_SET_TRANSFER_POLLED_RX:
			uart_tranfer_mode(io_desc, UART_POLLED_RX);
		break;

		case IORC_SET_TRANSFER_INTERRUPT_TX:
			uart_tranfer_mode(io_desc, UART_INTERRUPT_TX);
		break;

		case IORC_SET_TRANSFER_INTERRUPT_RX:
			uart_tranfer_mode(io_desc, UART_INTERRUPT_RX);
		break;

		case IORC_SET_PARITY:
			uart_set_parity(io_desc, *(uint8_t *)pValue);
		break;

		case IORC_SET_STOP_BIT:
			uart_set_stopbit(io_desc, *(uint8_t *)pValue);
		break;

		case IORC_TEST_SIGNAL:
			*(bool *)pValue = uart_test_signal(io_desc);
		break;

		case IORC_RELEASE_SIGNAL:
			uart_release_signal(io_desc);
		break;

		case IORC_GET_IO_SETTING:
			_uart_opt = uart_get_setting(io_desc);
			_com_param->baudrate = _uart_opt->baudrate;
			_com_param->charlength = _uart_opt->charlength;
			_com_param->paritytype = _uart_opt->paritytype;
			_com_param->stopbits = _uart_opt->stopbits;
		break;

		default:
			 _ret_status = pdFAIL;
		break;
	}
	
	return _ret_status;
}


io_descriptor_t uart_io_open(IO_path path_name, const uint8_t flag)
{
	return uart_open(path_name, flag);
}


portBASE_TYPE uart_io_close(io_descriptor_t io_desc, const uint8_t flag)
{
	if(uart_close(io_desc, flag) == UART_STATUS_OK) return pdPASS;

	return pdFAIL;
}


portBASE_TYPE uart_io_write(io_descriptor_t io_desc, const void *pBuf, uint32_t size, io_rw_flag_t flag)
{
	portBASE_TYPE _ret_status = pdFAIL;

	switch(flag) {
		case IORWF_BYTE_ORDER:
			if (uart_write_byte(io_desc, pBuf, size) == UART_STATUS_OK) {
				_ret_status = pdPASS;
			}
		break;

		case IORWF_WORD_ORDER:
			if (uart_write_word(io_desc, pBuf, size) == UART_STATUS_OK) {
				_ret_status = pdPASS;
			}
		break;

		default: break;
	}
	
	return _ret_status;
}


portBASE_TYPE uart_io_read(io_descriptor_t io_desc, void *pBuf, uint32_t size, io_rw_flag_t flag)
{
	portBASE_TYPE _ret_status = pdFAIL;
	
	switch(flag) {
		case IORWF_BYTE_ORDER:
			if(uart_read_byte(io_desc, pBuf, size) == UART_STATUS_OK) {
				_ret_status = pdPASS;
			}
		break;
	
		case IORWF_WORD_ORDER:
			if(uart_read_word(io_desc, pBuf, size) == UART_STATUS_OK) {
				_ret_status = pdPASS;
			}
		break;

		default: break;
	}
	
	return _ret_status;
}

#endif /* UART_PERIPHERAL_ACTIVE */
